package com.zy.batiya.service.impl;

import java.math.BigDecimal;
import java.text.ParseException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.zy.batiya.controller.ApiController;
import com.zy.batiya.domain.InventoryItem;
import com.zy.batiya.domain.Order;
import com.zy.batiya.domain.Price;
import com.zy.batiya.mapper.InventoryItemMapper;
import com.zy.batiya.mapper.OrderMapper;
import com.zy.batiya.mapper.PriceMapper;
import com.zy.batiya.service.ApiService;
import com.zy.batiya.util.DateUtil;
import com.zy.batiya.util.https.HttpsUtil;

@Transactional
@Component
public class ApiServiceImpl implements ApiService{
  
  private Logger logger = LoggerFactory.getLogger(ApiServiceImpl.class);
  
  private final String url = "https://openapi.fvt.tujia.com/houseImport-web/api/";
  private final String apiKey = "cef60315dd2b4546a6e5f1bc7c9e678d";
  
  @Autowired
  private InventoryItemMapper inventoryItemMapper;
  
  @Autowired
  private PriceMapper priceMapper;
  
  @Autowired
  private OrderMapper orderMapper;
  
  @Autowired
  private HttpsUtil httpsUtil;
  
  @Override
  public JSONObject searchInventory(Map<String, String> paramMap) {
    JSONObject rs = new JSONObject();
    try {
      String begin = paramMap.get("checkin");
      String end = paramMap.get("checkout");
      int offset = DateUtil.getOffset(begin, end,  "yyyy-MM-dd");
      paramMap.put("days", String.valueOf(offset));
      List<Map<String,String>> inventoryItemes = inventoryItemMapper.searchInventory(paramMap);
      
      if(inventoryItemes != null && inventoryItemes.size() > 0){
        int size = inventoryItemes.size();
        int reqSize = Integer.valueOf(paramMap.get("quantity"));
        
        if(size >= reqSize){
          //库存充足 判断总价
          double req_total_price = Double.valueOf(paramMap.get("total_price"));
          List<String> dt_list = DateUtil.getDtList(begin, end, "yyyy-MM-dd");
          double total_price = 0;
          for(String dt:dt_list){
            List<Price> prices = priceMapper.search(paramMap.get("partner_pid"),dt);
            if(prices != null && prices.size()>0){
              double cost = prices.get(0).getAmount();
              total_price += cost;
            }
          }
          
          if(total_price == req_total_price){
            rs.put("result_code", "0");
            rs.put("message", "ok");
            rs.put("partner_uid", paramMap.get("partner_uid"));
            rs.put("partner_pid", paramMap.get("partner_pid"));
            rs.put("total_price", paramMap.get("total_price"));
            rs.put("currency", paramMap.get("currency"));
          }else{
            //价格不符合
            rs.put("result_code", "4");
            rs.put("message", "价格发生变化");
            rs.put("partner_uid", paramMap.get("partner_uid"));
            rs.put("partner_pid", paramMap.get("partner_pid"));
            rs.put("total_price", total_price);
            rs.put("currency", paramMap.get("currency"));
          }
        }else{
          //库存不足
          rs.put("result_code", "1");
          rs.put("message", "库存不足");
          rs.put("partner_uid", paramMap.get("partner_uid"));
          rs.put("partner_pid", paramMap.get("partner_pid"));
          rs.put("total_price", paramMap.get("total_price"));
          rs.put("currency", paramMap.get("currency"));
        }
      }else{
        //库存不足
        rs.put("result_code", "1");
        rs.put("message", "库存不足");
        rs.put("partner_uid", paramMap.get("partner_uid"));
        rs.put("partner_pid", paramMap.get("partner_pid"));
        rs.put("total_price", paramMap.get("total_price"));
        rs.put("currency", paramMap.get("currency"));
      }
    } catch (Exception e) {
      e.printStackTrace();
      logger.error("searchInventory exception..." + JSONObject.toJSONString(paramMap));
    }
    return rs;
  }

  @Override
  public JSONObject addOrder(Map<String, String> paramMap) {
    JSONObject rs = new JSONObject();
    try {
      //更新库存信息
      Map<String, String> searchMap = new HashMap<String,String>();
      searchMap.put("checkin", paramMap.get("checkin"));
      searchMap.put("checkout", paramMap.get("checkout"));
      searchMap.put("partner_pid", paramMap.get("partner_pid"));
      searchMap.put("partner_uid", paramMap.get("partner_uid"));
      
      String begin = paramMap.get("checkin");
      String end = paramMap.get("checkout");
      int offset = DateUtil.getOffset(begin, end,  "yyyy-MM-dd");
      searchMap.put("days", String.valueOf(offset));
      
      List<Map<String,String>> inventoryItemes = inventoryItemMapper.searchInventory(searchMap);
      
      if(inventoryItemes != null && inventoryItemes.size() > 0){
        int size = inventoryItemes.size();
        int reqSize = Integer.valueOf(paramMap.get("number_of_units"));
        
        if(size >= reqSize){
          Order order = new Order();
          order.setCheckin(DateUtil.getDateByStr("yyyy-MM-dd", paramMap.get("checkin")));
          order.setCheckout(DateUtil.getDateByStr("yyyy-MM-dd", paramMap.get("checkout")));
          order.setCreatetime(new Date());
          order.setCurrency(paramMap.get("currency"));
          order.setGuest_count(Integer.valueOf(paramMap.get("guest_count")));
          order.setLink_email(paramMap.get("link_email"));
          order.setLink_man(paramMap.get("link_man"));
          order.setLink_phone(paramMap.get("link_phone"));
          order.setNumber_of_units(Integer.valueOf(paramMap.get("number_of_units")));
          order.setOid(paramMap.get("oid"));
          order.setPartner_pid(paramMap.get("partner_pid"));
          order.setPartner_uid(paramMap.get("partner_uid"));
          order.setStatus(1);
          order.setTotal_price(new BigDecimal(paramMap.get("total_price")));
          
          //保存订单
          orderMapper.insert(order);
          
          //库存充足 判断总价
          double req_total_price = Double.valueOf(paramMap.get("total_price"));
          List<String> dt_list = DateUtil.getDtList(begin, end, "yyyy-MM-dd");
          double total_price = 0;
          for(String dt:dt_list){
            List<Price> prices = priceMapper.search(paramMap.get("partner_pid"),dt);
            if(prices != null && prices.size()>0){
              double cost = prices.get(0).getAmount();
              total_price += cost;
            }
          }
          
          if(total_price == req_total_price){
            //选择房间
            for(int j=0;j<reqSize;j++){
              Map<String,String> item = inventoryItemes.get(j);
              String roomId = String.valueOf(item.get("roomId"));
              Map<String,String> updateMap = new HashMap<String,String>();
              updateMap.put("isOrdered", "1");
              updateMap.put("orderId", String.valueOf(order.getId()));
              updateMap.put("partnerId", "1");
              updateMap.put("updatetime", DateUtil.getDateStr("yyyy-MM-dd HH:mm:ss", new Date()));
              updateMap.put("partner_pid", paramMap.get("partner_pid"));
              updateMap.put("partner_uid", paramMap.get("partner_uid"));
              updateMap.put("checkin", begin);
              updateMap.put("checkout", end);
              updateMap.put("roomId", roomId);
              inventoryItemMapper.updateByOrder(updateMap);
            }
            
            //结束 返回
            rs.put("result_code", 0);
            rs.put("message", "下单成功");
            rs.put("oid", paramMap.get("oid"));
            rs.put("partner_oid",order.getId());
            rs.put("booking_time", DateUtil.getDateStr("yyyy-MM-dd", new Date()));
            rs.put("order_status", 1);
            return rs;
          }else{
            //价格不符合
            rs.put("result_code", "4");
            rs.put("message", "价格发生变化");
            rs.put("oid", paramMap.get("oid"));
            rs.put("partner_oid", order.getId());
            rs.put("booking_time", DateUtil.getDateStr("yyyy-MM-dd", new Date()));
            rs.put("status", 1);
            return rs;
          }
        }else{
          Order order = new Order();
          order.setCheckin(DateUtil.getDateByStr("yyyy-MM-dd", paramMap.get("checkin")));
          order.setCheckout(DateUtil.getDateByStr("yyyy-MM-dd", paramMap.get("checkout")));
          order.setCreatetime(new Date());
          order.setCurrency(paramMap.get("currency"));
          order.setGuest_count(Integer.valueOf(paramMap.get("guest_count")));
          order.setLink_email(paramMap.get("link_email"));
          order.setLink_man(paramMap.get("link_man"));
          order.setLink_phone(paramMap.get("link_phone"));
          order.setNumber_of_units(Integer.valueOf(paramMap.get("number_of_units")));
          order.setOid(paramMap.get("oid"));
          order.setPartner_pid(paramMap.get("partner_pid"));
          order.setPartner_uid(paramMap.get("partner_uid"));
          order.setStatus(2);
          order.setTotal_price(new BigDecimal(paramMap.get("total_price")));
          
          //保存订单
          orderMapper.insert(order);
                 
          //库存不足
          rs.put("result_code", "1");
          rs.put("message", "库存不足");
          rs.put("oid", paramMap.get("oid"));
          rs.put("partner_oid", order.getId());
          rs.put("booking_time", DateUtil.getDateStr("yyyy-MM-dd", new Date()));
          rs.put("status", 1);
          
          return rs;
        }
      }else{
        //库存不足
        Order order = new Order();
        order.setCheckin(DateUtil.getDateByStr("yyyy-MM-dd", paramMap.get("checkin")));
        order.setCheckout(DateUtil.getDateByStr("yyyy-MM-dd", paramMap.get("checkout")));
        order.setCreatetime(new Date());
        order.setCurrency(paramMap.get("currency"));
        order.setGuest_count(Integer.valueOf(paramMap.get("guest_count")));
        order.setLink_email(paramMap.get("link_email"));
        order.setLink_man(paramMap.get("link_man"));
        order.setLink_phone(paramMap.get("link_phone"));
        order.setNumber_of_units(Integer.valueOf(paramMap.get("number_of_units")));
        order.setOid(paramMap.get("oid"));
        order.setPartner_pid(paramMap.get("partner_pid"));
        order.setPartner_uid(paramMap.get("partner_uid"));
        order.setStatus(2);
        order.setTotal_price(new BigDecimal(paramMap.get("total_price")));
        
        //保存订单
        orderMapper.insert(order);
        
        //库存不足
        rs.put("result_code", "1");
        rs.put("message", "库存不足");
        rs.put("oid", paramMap.get("oid"));
        rs.put("partner_oid", order.getId());
        rs.put("booking_time", DateUtil.getDateStr("yyyy-MM-dd", new Date()));
        rs.put("status", 1);
        return rs;
      }
    } catch (Exception e) {
      e.printStackTrace();
      logger.error("addOrder exception on " + JSONObject.toJSONString(paramMap));
      
      rs.put("result_code", 5);
      rs.put("message", "系统异常");
      rs.put("oid", paramMap.get("oid"));
      rs.put("partner_oid",0);
      rs.put("booking_time", DateUtil.getDateStr("yyyy-MM-dd", new Date()));
      rs.put("status", 0);
      return rs;
    }
  }

  @Override
  public JSONObject cancelOrder(Map<String, String> paramMap) {
    JSONObject rs = new JSONObject();
    try {
      List<Order> orders = orderMapper.search(paramMap);
     
      if(orders != null ){
        Order order = orders.get(0);
        Map<String,String> updateMap = new HashMap<String,String>();
        updateMap.put("isOrdered", "0");
        updateMap.put("orderId", String.valueOf(orders.get(0).getId()));
        updateMap.put("partnerId", "1");
        updateMap.put("updatetime", DateUtil.getDateStr("yyyy-MM-dd HH:mm:ss", new Date()));
        updateMap.put("checkin", DateUtil.getDateStr("yyyy-MM-dd", orders.get(0).getCheckin()));
        updateMap.put("checkout", DateUtil.getDateStr("yyyy-MM-dd", orders.get(0).getCheckout()));
        inventoryItemMapper.updateByOrder(updateMap);
        
        double penalty = getPenalty(order.getCheckin(),order.getTotal_price().doubleValue());
        
        rs.put("result_code", "0");
        rs.put("message", "ok");
        rs.put("oid", orders.get(0).getOid());
        rs.put("partner_oid", String.valueOf(orders.get(0).getId()));
        rs.put("penalty", penalty);
        rs.put("total_price", orders.get(0).getTotal_price());
        rs.put("cancel_time", String.valueOf(System.currentTimeMillis()));
        
        order.setStatus(2);
        order.setUpdatetime(new Date());
        order.setPenalty(new BigDecimal(penalty));
        orderMapper.update(order);
      }else{
        rs.put("result_code", "1");
        rs.put("message", "订单未找到");
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
    return rs;
  }

  private double getPenalty(Date checkin, double doubleValue) {
    checkin = DateUtil.getOffsetDay(checkin, -1);
    if(new Date().getTime() < (checkin.getTime() + 43200000)){
      return 0;
    }else{
      return doubleValue * 0.5d;
    }
  }

  @Override
  public void updateInventory(Map<String, String> paramMap) {
    try {
      String begin = paramMap.get("checkin");
      String end = paramMap.get("checkout");
      
      List<String> dts = DateUtil.getDtList(begin, end, "yyyy-MM-dd");
      
      for(String dt:dts){
        //同步库存变化
        String targetUrl = url + "inventory";
        Map<String, String> headerParam = new HashMap<String, String>();
        headerParam.put("apikey", apiKey);
        
        JSONObject req = new JSONObject();
        req.put("partner_uid", paramMap.get("partner_uid"));
        req.put("partner_pid", paramMap.get("partner_pid"));
        
        JSONArray inventorys = new JSONArray();
        
        JSONObject inventoryObj = new JSONObject();
        
        inventoryObj.put("begin_date", dt);
        inventoryObj.put("end_date", DateUtil.getDateStr("yyyy-MM-dd", DateUtil.getOffsetDay(DateUtil.getDateByStr("yyyy-MM-dd", dt), 1)));
         
        Map<String, String> searchMap = new HashMap<String, String>();
        
        searchMap.put("partner_uid", paramMap.get("partner_uid"));
        searchMap.put("partner_pid", paramMap.get("partner_pid"));
        searchMap.put("dt", dt);
        
        inventoryObj.put("quantity", inventoryItemMapper.getQuantity(paramMap));
        inventorys.add(inventoryObj);
        
        JSONArray prices = new JSONArray();
        
        JSONObject priceObj = new JSONObject();
        priceObj.put("begin_date", dt);
        priceObj.put("end_date", DateUtil.getDateStr("yyyy-MM-dd", DateUtil.getOffsetDay(DateUtil.getDateByStr("yyyy-MM-dd", dt), 1)));
        Price price = priceMapper.findByPid(Integer.valueOf(paramMap.get("partner_pid"))).get(0);
        priceObj.put("amount", price.getAmount());
        prices.add(priceObj);
        
        req.put("inventorys", inventorys);
        req.put("prices", prices);
        
        logger.info(httpsUtil.postBody(targetUrl, JSONObject.toJSONString(req), headerParam));
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  @Override
  public void updateInventoryItemByCancel(String oid) {
    Map<String,String> paramMap = new HashMap<String,String>();
    paramMap.put("oid", oid);
    List<Order> orders = orderMapper.search(paramMap);
    if(orders != null && orders.size()>0){
      Order order = orders.get(0);
      Map<String,String> updateMap = new HashMap<String,String>();
      updateMap.put("isOrdered", "0");
      updateMap.put("orderId", String.valueOf(order.getId()));
      updateMap.put("partnerId", "1");
      updateMap.put("updatetime", DateUtil.getDateStr("yyyy-MM-dd HH:mm:ss", new Date()));
      updateMap.put("partner_pid", paramMap.get("partner_pid"));
      updateMap.put("partner_uid", paramMap.get("partner_uid"));
      updateMap.put("checkin", DateUtil.getDateStr("yyyy-MM-dd", order.getCheckin()));
      updateMap.put("checkout", DateUtil.getDateStr("yyyy-MM-dd", order.getCheckout()));
      inventoryItemMapper.updateByOrder(updateMap);
      //通知途家库存变更
      this.updateInventory(updateMap);
    }
  }

  @Override
  public JSONObject searchOrder(Map<String, String> paramMap) {
    List<Order> orders = orderMapper.search(paramMap);
    JSONObject rs = new JSONObject();
    if(orders != null && orders.size() > 0){
      Order order = orders.get(0);
      rs.put("result_code", "0");
      rs.put("message", "ok");
      rs.put("partner_oid", String.valueOf(order.getId()));
      rs.put("order_status", order.getStatus());
      rs.put("order_status_desc", "");
    }else{
      rs.put("result_code", "0");
      rs.put("message", "order not found");
      rs.put("partner_oid", "");
      rs.put("order_status", "");
      rs.put("order_status_desc", "");
    }
    return rs;
  }

  @Override
  public String getical(Map<String, String> paramMap) throws ParseException {
    List<InventoryItem> items = inventoryItemMapper.findICal(paramMap);
    StringBuffer rs = new StringBuffer();
    rs.append("BEGIN:VCALENDAR"+ "\n");
    rs.append("VERSION:2.0"+ "\n");
    rs.append("PRODID:-//Booking.com, b.v.//NONSGML v1.0//EN"+ "\n");
    rs.append("CALSCALE:GREGORIAN"+ "\n");
    rs.append("METHOD:PUBLISH"+ "\n");
    if(items != null){
      for(InventoryItem item:items){
        rs.append("BEGIN:VEVENT" + "\n");
        rs.append("DTSTART;VALUE=DATE:" + DateUtil.getDateStr("yyyyMMdd", DateUtil.getDateByStr("yyyy-MM-dd", item.getDt())) + "\n");
        rs.append("DTEND;VALUE=DATE:" + DateUtil.getDateStr("yyyyMMdd", DateUtil.getDateByStr("yyyy-MM-dd", DateUtil.getOffsetDay(item.getDt(), 1, "yyyy-MM-dd"))) + "\n");
        rs.append("UID:" + item.getPartnerId() + "\n");
        rs.append("SUMMARY: BOOKED" + "\n");
        rs.append("END:VEVENT" + "\n");
      }
    }
    rs.append("END:VCALENDAR");
    return rs.toString();
  }
}
